﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network;
using System.Threading;
using System.IO;
using GameStateManagement;

namespace Tetris_AntiGravity.network
{
    class Server
    {

        NetPeerConfiguration config;
        NetServer servidor;
        public bool conectado = false;
        HiloServidor hserv;
        Thread hilo;
        ConnectionScreen connectionScreen;
        
        public Server(string nombre, ConnectionScreen connectionScreen)
        {
            config = new NetPeerConfiguration(nombre);
            config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            config.Port = 14242;
            config.MaximumConnections = 2;
            servidor = new NetServer(config);
            this.connectionScreen = connectionScreen;
        }

        public void inicializarServidor()
        {
            servidor.Start();

            hserv = new HiloServidor(servidor, new ServerCallbak(ResultadoConexion));

            hilo = new Thread(hserv.esperarDatos);

            hilo.Start();
            //hilo.Join();
        }

        public void ApagarServidor()
        {
            hserv.ApagarServidor();
            hilo.Abort();

        }

        public  void ResultadoConexion(int resultado)
        {
            
            if(servidor.Connections.Count==1)
                connectionScreen.CrearCliente("", "localhost");
            
            Console.WriteLine("conectado");
        }
    }

    public delegate void ServerCallbak(int n);

    public class HiloServidor
    {
        NetServer servidor;
        ServerCallbak callback;
        Boolean activo;

        List<Mundo> mundo=new List<Mundo>();

        public HiloServidor(NetServer servidor, ServerCallbak callback)
        {
            this.servidor = servidor;
            this.callback = callback;
            this.activo = true;
        }

        public void ApagarServidor(){
            activo = false;
        }

        public void esperarDatos() {
            double nextSendUpdates = NetTime.Now;

            while (activo)
            {
                NetIncomingMessage msg;
                while ((msg = servidor.ReadMessage()) != null)
                {
                    switch (msg.MessageType)
                    {
                        case NetIncomingMessageType.DiscoveryRequest:
                            //
                            // Server received a discovery request from a client; send a discovery response (with no extra data attached)
                            //
                            servidor.SendDiscoveryResponse(null, msg.SenderEndpoint);
                            break;
                        
                        case NetIncomingMessageType.StatusChanged:
                            NetConnectionStatus status = (NetConnectionStatus)msg.ReadByte();
                            if (status == NetConnectionStatus.Connected)
                            {
                                //
                                // A new player just connected!
                                //
                                Console.WriteLine(msg.SenderEndpoint.Address + " conectado!");

                                callback(1);
                            }

                            break; 

                        case NetIncomingMessageType.Data:

                            if (msg.SenderConnection.RemoteEndpoint.Address.ToString().Equals("127.0.0.1"))
                                Console.Write("");

                            TipoPaquete tipopaq = (TipoPaquete)msg.ReadByte();
                            
                            Console.WriteLine(msg.SenderConnection+" " + tipopaq);

                            if (tipopaq == TipoPaquete.INICIALIZACION)
                            {
                                JugadorNetwork jugNet = new JugadorNetwork();
                                //msg.ReadAllFields(jugNet);
                                jugNet.leerPaquete(msg);
                                foreach (NetConnection player in servidor.Connections)
                                {
                                    if (player == msg.SenderConnection)
                                    {
                                        Mundo temp = new Mundo();
                                        jugNet.id = player.RemoteUniqueIdentifier;
                                        temp.jn = jugNet;
                                        temp.player = player;
                                        mundo.Add(temp);
                                    }

                                    else
                                    {
                                        NetOutgoingMessage outmsg = servidor.CreateMessage();
                                        outmsg.Write((byte)TipoPaquete.INICIALIZACION);
                                        jugNet.escribirPaquete(outmsg);
                                        //outmsg.WriteAllFields(jugNet);
                                        servidor.SendMessage(outmsg, player, NetDeliveryMethod.ReliableOrdered);
                                    }
                                }
                            }

                            if (tipopaq == TipoPaquete.ACTUALIZAR)
                            {
                                
                                
                                JugadorNetwork jugNet = new JugadorNetwork();
                                jugNet.leerPaquete(msg);
                                //msg.ReadAllFields(jugNet);

                                foreach (Mundo tempMundo in mundo)
                                {
                                    if (tempMundo.player == msg.SenderConnection)
                                    {
                                        tempMundo.jn = jugNet;
                                        
                                    }
                                }

                                foreach (NetConnection player in servidor.Connections)
                                {
                                    foreach (Mundo tempMundo in mundo)
                                    {
                                        //if (tempMundo.player != player)
                                        //{
                                            NetOutgoingMessage outmsg = servidor.CreateMessage();
                                            outmsg.Write((byte)TipoPaquete.ACTUALIZAR);
                                            tempMundo.jn.escribirPaquete(outmsg);
                                            //outmsg.WriteAllFields(tempMundo.jn);
                                            servidor.SendMessage(outmsg, player, NetDeliveryMethod.ReliableOrdered);
                                        //}
                                        
                                    } 
                                }
                            }

                            if (tipopaq == TipoPaquete.MOVIMIENTO)
                            {
                                TipoAtaque ataque = (TipoAtaque)msg.ReadByte();
                                foreach (NetConnection player in servidor.Connections)
                                {
                                    if (player != msg.SenderConnection)
                                    {
                                        NetOutgoingMessage outmsg = servidor.CreateMessage();
                                        outmsg.Write((byte)TipoPaquete.MOVIMIENTO);
                                        outmsg.Write((byte)ataque);
                                        servidor.SendMessage(outmsg, player, NetDeliveryMethod.ReliableOrdered);
                                    }

                                    
                                }
                            }

                            break;
                    }
                }
            }

            servidor.Shutdown("Bye");
        }
    }

    

    class Mundo
    {
        public JugadorNetwork jn;
        public NetConnection player;
    }
}
